<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="gKr6Z" id="gKr6Z"><span data-lake-id="ucdbe5afb" id="ucdbe5afb">典型回答</span></h1>
  <p data-lake-id="uedf22777" id="uedf22777"><br></p>
  <p data-lake-id="u4b1b0e22" id="u4b1b0e22"><span data-lake-id="u77ae2634" id="u77ae2634">可重入锁是一种多线程同步机制，允许</span><strong><span data-lake-id="u5610013a" id="u5610013a">同一线程</span></strong><span data-lake-id="uee5f174a" id="uee5f174a">多次获取同一个锁而不会导致死锁。这意味着一个线程可以在持有锁的情况下再次请求并获得相同的锁，而不会被自己阻塞。可重入锁有助于避免死锁和提高代码的可维护性，因为它允许在一个线程中嵌套地调用锁定的方法。</span></p>
  <p data-lake-id="udc2ec2ff" id="udc2ec2ff"><span data-lake-id="u23326465" id="u23326465">​</span><br></p>
  <p data-lake-id="uc7a31f39" id="uc7a31f39"><span data-lake-id="uf8d8d736" id="uf8d8d736">如我们常用的synchronized和reentrantLock都是比较典型的可重入锁。也就是说，</span><span data-lake-id="uc748587a" id="uc748587a" style="color: rgb(18, 18, 18)">在一个线程调用synchronized方法的同时，可以在其方法体内部调用该对象另一个synchronized方法，也就是说一个线程得到一个对象锁后再次请求该对象锁。</span></p>
  <p data-lake-id="ub2e168f3" id="ub2e168f3"><span data-lake-id="ucc14e909" id="ucc14e909" style="color: rgb(18, 18, 18)">​</span><br></p>
  <pre lang="java"><code>
public class ReentrantLockTest {

    public static void main(String[] args) {
        ReentrantLockTest reentrantLockTest = new ReentrantLockTest();
        reentrantLockTest.method1();
    }

    public synchronized void method1(){
        method2();
        System.out.println("invoke method1");
    }

    public synchronized void method2() {
        System.out.println("invoke method2");
    }
}

</code></pre>
  <p data-lake-id="u7842eee8" id="u7842eee8"><span data-lake-id="u1b4f8654" id="u1b4f8654">如以上代码，即可输出：</span></p>
  <p data-lake-id="u2d6b672d" id="u2d6b672d"><span data-lake-id="u19b7a534" id="u19b7a534">​</span><br></p>
  <pre lang="java"><code>
invoke method2
invoke method1
</code></pre>
  <p data-lake-id="u57503fb6" id="u57503fb6"><br></p>
  <p data-lake-id="u50361326" id="u50361326"><span data-lake-id="u171148e1" id="u171148e1">在可重入锁的实现上，一般是先要记录下来当前锁是归属于哪个线程的，然后再记录当前锁被重入了多少次。这样在加锁的时候判断是不是当前线程持有的锁，如果是则重入次数+1，否则重入失败。</span></p>
  <p data-lake-id="u1a1c61b1" id="u1a1c61b1"><span data-lake-id="u358f4aa5" id="u358f4aa5">​</span><br></p>
  <p data-lake-id="u096bebe6" id="u096bebe6"><span data-lake-id="uaf8682a5" id="uaf8682a5">在解锁时也同理，锁是当前线程加的，那就重入次数-1，直到等于0的时候，直接解锁。</span></p>
  <p data-lake-id="u6c5b13cc" id="u6c5b13cc"><span data-lake-id="u78236905" id="u78236905">​</span><br></p>
  <p data-lake-id="u0ce0e961" id="u0ce0e961"><span data-lake-id="ubb5eeba1" id="ubb5eeba1">以下就是reentrantLock的加锁代码：</span></p>
  <p data-lake-id="uab612da5" id="uab612da5"><span data-lake-id="u361ee8cf" id="u361ee8cf">​</span><br></p>
  <pre lang="java"><code>
if (current == getExclusiveOwnerThread()) {
     int nextc = c + acquires;
     if (nextc &lt; 0)
     	throw new Error("Maximum lock count exceeded");
     setState(nextc);
     return true;
 }
</code></pre>
  <p data-lake-id="u45bd774e" id="u45bd774e"><br></p>
  <p data-lake-id="ucb9f7f6a" id="ucb9f7f6a"><span data-lake-id="u26caac96" id="u26caac96">以下就是reentrantLock的解锁代码：</span></p>
  <pre lang="java"><code>
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}
</code></pre>
 </body>
</html>